<!--
@description    表格展示
@author         秦俊强
@email          458112865@qq.com
@create         2020-02-01 17:30
-->

<template>
  <div class="table-box" :class="k + '-box'">
    <!-- 表格内容 start -->
    <div v-if="k !== 'audit'">
      <!-- 针对批量编辑 可以输入分数 start -->
      <a-table v-if="isEditAll && showEdit('input')"
               :loading="loading" :pagination="false"
               :scroll="tableData[tableKey].scroll"
               :columns="tableData[tableKey].columns"
               :dataSource="editAllData">
        <template v-for="k in editDataKeys[tableKey]"
                  :slot="k" slot-scope="text, record, ind">
          <a-input class="edit-input" type="number" :value="text"
                   @change="handleChange($event, k, ind)" />
        </template>
      </a-table>
      <!-- 针对批量编辑 可以输入分数 end -->

      <!-- 针对批量编辑 可以输入权重百分比或区间 start -->
      <a-table v-else-if="isEditAll && showEdit('section')"
               :loading="loading" :pagination="false"
               :scroll="tableData[tableKey].scroll"
               :columns="tableData[tableKey].columns"
               :dataSource="editAllData">
        <template v-for="k in editDataKeys[tableKey]"
                  :slot="k" slot-scope="text, record, ind">
          <!-- 编辑百分比 -->
          <div class="weight-per" v-if="record.indexType == '1'">
            <a-input class="edit-input" type="number" :value="text"
                     @change="handleChange($event, k, ind)" />
            <span> %</span>
          </div>

          <!-- 编辑区间 -->
          <div class="weight-sec" v-if="record.indexType == '2'" >
            <a-input class="edit-input" type="number" :value="text[0]"
                     @change="handleChange($event, k, ind, 0)" />
            <span> - </span>
            <a-input class="edit-input" type="number" :value="text[1]"
                     @change="handleChange($event, k, ind, 1)" />
          </div>
        </template>
      </a-table>
      <!-- 针对批量编辑 可以输入权重百分比或区间 end -->


      <!-- //////////////////// 分界线 ////////////////////  -->


      <!-- 【默认展示表格】针对单行编辑 start -->
      <a-table v-else :loading="loading" :pagination="false"
               :scroll="tableData[tableKey].scroll"
               :columns="tableData[tableKey].columns"
               :dataSource="tableData[tableKey].dataSource">
        <template v-for="k in editDataKeys[tableKey]"
                  :slot="k" slot-scope="text, record, ind">
          <!-- 输入框编辑 start -->
          <div v-if="record.isEditRow">
            <a-input v-if="showEdit('input') && record.indexCode == undifined"
                     class="edit-input" type="text"
                     :value="editRowData[k]"
                     @change="handleChange($event, k)"
                     @pressEnter="checkedRow(ind, 'saveRow')" />
            <a-input v-else-if="showEdit('input') && record.indexCode != undifined"
                     class="edit-input" type="number"
                     :value="editRowData[k]"
                     @change="handleChange($event, k)"
                     @pressEnter="checkedRow(ind, 'saveRow')" />
            <!-- 编辑权重 start -->
            <div v-if="showEdit('section')">
              <!-- 编辑百分比 -->
              <div class="weight-per"
                   v-if="record.indexType === '1'">
                <a-input class="edit-input" type="number"
                         :value="editRowData[k]"
                         @change="handleChange($event, k)"
                         @pressEnter="checkedRow(ind, 'saveRow')" />
                <span> %</span>
              </div>

              <!-- 编辑区间 -->
              <div class="weight-sec"
                   v-if="record.indexType === '2'">
                <a-input class="edit-input" type="number"
                         :value="editRowData[k][0]"
                         @change="handleChange($event, k, 0)"
                         @pressEnter="checkedRow(ind, 'saveRow')" />
                <span> - </span>
                <a-input class="edit-input" type="number"
                         :value="editRowData[k][1]"
                         @change="handleChange($event, k, 1)"
                         @pressEnter="checkedRow(ind, 'saveRow')" />
              </div>
            </div>
            <!-- 编辑权重 end -->
          </div>
          <!-- 输入框编辑 end -->


          <!-- 只读状态 -->
          <span v-else class="spanStyle" :title=text>{{ text }}</span>
        </template>

        <!-- 编辑按钮 -->
        <template :slot="'operation'" slot-scope="text, record, ind">
          <span v-if="k === 'mgr' && ['0', '1', '4'].indexOf(status) < 0"
                class="btn-disabled" title="审核中或已审核时不能进行编辑">编辑</span>
          <span v-else-if="k === 'weight' && !record.isEditRow && !isEditRow() && isNotCurrentMonth()"
                class="btn-disabled" @click="checkedRow(ind, 'editRow')">编辑</span>
          <span v-else-if="!record.isEditRow && !isEditRow()"
                class="btn-edit" @click="checkedRow(ind, 'editRow')">编辑</span>



          <div v-else-if="record.isEditRow">
            <span class="btn-save" @click="checkedRow(ind, 'saveRow')">保存</span>
            <span class="btn-cancel" @click="checkedRow(ind, 'cancelRow')">取消</span>
          </div>

          <span v-else class="btn-disabled"
                title="当前有正在编辑的内容">编辑</span>
        </template>
      </a-table>
      <!-- 【默认展示表格】针对单行编辑 end -->
    </div>
    <!-- 表格内容 end -->

    <!-- 绩效审核记录 表格 start -->
    <div v-else>
      <a-table :loading="loading" :pagination="false"
               :columns="auditTabData.columns"
               :dataSource="auditTabData.dataSource"></a-table>
    </div>
    <!-- 绩效审核记录 表格 end -->



    <!-- 分页 start -->
    <div class="pagination-box">
      <a-pagination :current="pageData.pageNo"
                    :pageSize="pageData.pageSize"
                    :total="pageData.total"
                    :pageSizeOptions="['10', '15', '20', '30']"
                    showSizeChanger
                    @change="changePage"
                    @showSizeChange="onShowSizeChange" />
    </div>
    <!-- 分页 end -->

  </div>
</template>



<script>

  /* 引入 api 接口 */
  import { apiConfig } from './api.config.js';

  /* 引入表格配置文件 */
  import { auditTabData, getCommonTabTem } from './table.config.js';




  export default {
    name: 'kpi-table-common',

    /* 父组件传值 */
    props: {
      /**
       * 标识模块，用来判断该调用哪些接口（必传）
       * k = 'fill'         绩效管理-绩效填报
       * k = 'target'       绩效管理-设定绩效目标值
       * k = 'audit'        绩效审核-绩效审核记录
       * k = 'weight'       绩效维护-权重管理
       * k = 'mgr'          绩效管理-绩效汇总计算
       * */
      k: '',

      /**
       * 表头数据
       * */
      headerInfo: {},

      /* 考核期，调用接口传参（必传） */
      date: '',

      /* 考核指标，调用接口传参（非必须，默认空） */
      targets: {
        type: Array,
        default: []
      },

      /* 维度 */
      dimensions: {
        type: Array,
        default: []
      },

      /* 标识是否是编辑状态（非必须，默认 false） */
      isEditAll: false,

      /* 审核状态 */
      status: ''
    },

    data() {
      return {
        /* 数据是否加载中 */
        loading: false,

        /* 表格参数 */
        tableData: {},

        /* 绩效审核记录 使用固定表头 */
        auditTabData: auditTabData(),

        /* 要编辑的单元格的 key */
        editDataKeys: {},

        /* 要编辑的数值，点击保存的时候传这个数组 */
        editAllData: [],

        /* 当前要进行编辑的某一行数据 */
        editRowData: {},

        /* 标记当前选择的部门 */
        tableKey: '',

        /* 分页参数 */
        pageData: {
          pageNo: 1,
          pageSize: 10,
          total: null
        }
      };
    },

    created() {
      this.initTableData();

      /* 监听组织类型 index 变化 */
      this.$watch('headerInfo.index', () => {
        let headerInfo = this.headerInfo;
        this.tableKey = headerInfo.arr[headerInfo.index].code;
      });

      /* 监听 isEditAll 的状态变化 */
      this.$watch('isEditAll', () => {
        if (!this.isEditAll) { return; }

        let dataSource = this.tableData[this.tableKey].dataSource;
        dataSource = JSON.parse(JSON.stringify(dataSource));        // 解除链式关系

        // 如果是权重管理页面
        if (this.k === 'weight') { dataSource = this.getWeightArr(dataSource, 'edit'); }

        // 处理格式
        for (let i = 0; i < dataSource.length; i++) {
          let item = dataSource[i];
          dataSource[i] = this.getDataSource(item, 'edit');
        }

        // 赋值
        this.editAllData = dataSource;
      });
    },

    methods: {

      /**
       * ind 标记是第几行的数据
       *
       * 编辑行 editRow
       * 保存行 saveRow
       * 取消要编辑的行数据 cancelRow
       * */
      checkedRow(ind, str) {
        let t = this;

        if (str === 'saveRow') {
          t.submitData('save');
          return;
        }

        t.tableData = t.getNewTableData(t.tableData, t.tableKey, ind, str);
        t.updateIsEditRow();
      },

      /* 更新父组件中的状态 */
      updateIsEditRow() {
        this.$parent.isEditRow = this.isEditRow();
      },

      /* 返回当前是否有正在编辑的行 */
      isEditRow() {
        let dataSource = this.tableData[this.tableKey].dataSource;
        return dataSource.some((item) => { return item.isEditRow; });
      },

      /* 返回当前是否有正在编辑的行 */
      isNotCurrentMonth() {
          let currentDate = new Date();
          let currentYear = currentDate.getFullYear();
          let currentMonth = currentDate.getMonth();
          if(currentMonth == 0){
             currentMonth = 12;
             currentYear = currentYear - 1;
          }
          currentMonth = currentMonth < 10 ? '0'+currentMonth : currentMonth;
          let sign = this.date != (currentYear+''+currentMonth);
          debugger;
          return sign;
      },

      /**
       * 返回数值
       * @return { Number | val }
       * */
      getNum(val) {
        let num = val;

        // 如果存在小数点，并且小数位数超过 2 位时
        if (val.indexOf('.') >= 0 && val.split('.')[1].length > 2) {
          num = parseFloat(val).toFixed(2);
        } else {
          // 将字符串转成浮点数返回
          num = parseFloat(val);
        }

        // 处理 NaN 值
        if (isNaN(num)) { num = 0; }

        return num;
      },

      /**
       * 返回区间数组
       *
       * val    { String }   要替换的值
       * arr    { Array }    原来的数组
       * _ind   { Number }   要替换数组的序号
       *
       * @return { Array }
       * */
      switchArr(val, arr, _ind) {
        // TODO 特殊处理一下 arr 后台格式不稳定 很有可能是字符串 "1,5" 的格式 需要转成数组，后期稳定后删除
        if (typeof arr === 'string' && arr[0] !== '[') {
          arr = arr.split(',').map((val) => { return this.getNum(val); });
        }

        if (_ind === 0) { arr = [val, arr[1]]; }
        if (_ind === 1) { arr = [arr[0], val]; }

        return arr;
      },

      /**
       * 监听输入值的变化
       *
       *  e => 当前编辑输入框的信息
       *  k => 当前编辑的部门 code
       *  ind => 当前编辑的是第几行
       *
       *  valInd => 针对【权重管理】编辑区间
       * */
      handleChange(e, k, ind, valInd) {
        let numStr = e.target.value;
        // 最大长度限制 19 位


        /**
         * 1. 批量编辑的情况用 editAllData
         * 2. 单行编辑的情况用 editRowData
         * */

        /* 1. 批量编辑的情况 */
        if (this.isEditAll) {
          if (numStr.length > 19) { return; }
          // 编辑区间
          if (typeof valInd === 'number') {
            this.editAllData[ind][k] = this.switchArr(numStr, this.editAllData[ind][k], valInd);
            return;
          }
          this.editAllData[ind][k] = numStr;
          return;
        }

        /* 2. 单个编辑的情况 */
        // 编辑区间
        if (typeof ind === 'number') {
          if (numStr.length > 19) { return; }
          this.editRowData[k] = this.switchArr(numStr, this.editRowData[k], ind);
          return;
        }
        if (numStr.length > 200) { return; }
        this.editRowData[k] = numStr;
      },

      /* 初始化表头数据 */
      initTableData() {
        let headerInfo = this.headerInfo;
        this.tableKey = headerInfo.arr[headerInfo.index].code;

        // 绩效审核记录模块
        if (this.k === 'audit') {
          this.getAuditData();
          return;
        }
        for (let i = 0; i < headerInfo.arr.length; i++) {
          let item = headerInfo.arr[i];
          this.tableData[item.code] = this.getTabHeaderTem(item.tabHeader, item.code);
        }

        this.update(true);
      },

      /**
       * 返回表头模板，转换成第三方 UI 框架表格组件需要的格式
       * */
      getTabHeaderTem(arr, k) {
        this.editDataKeys[k] = [];
        let newArr = getCommonTabTem(arr, this.k);
        let width = (this.k === 'weight') ? 140 : 100;

        /* 3. 接口返回数组的前 4 项都可以忽略，所以从第 5 个开z始循环 */
        for (let i = 4; i < arr.length; i++) {
          let item = arr[i];

          newArr.splice(newArr.length - 1, 0, {
            title: item.name,
            align: 'center',
            width: width,
            dataIndex: item.code,
            scopedSlots: { customRender: item.code },
          });

          this.editDataKeys[k].push(item.code);
        }

        /* 5. 计算表格的横向滚动数值 */
        let num = (() => {
          return newArr.reduce((total, obj) => {
            let n = (typeof obj.width === 'number') ? obj.width : 0;
            return total + n;
          }, 0);
        })();
        return {
          scroll: { x: num, y: '500px' },
          columns: newArr,
          dataSource: [],
        };

      },

      /* 显示输入框类型 */
      showEdit(str) {
        let map = {
          /* 绩效填报 fill | 绩效目标值 target | 绩效汇总计算 mgr */
          input: ['fill', 'target', 'mgr'],

          /* 权重管理 weight */
          section: ['weight']
        }

        return map[str] && (map[str].indexOf(this.k) >= 0);
      },

      /* 监听页码改变 */
      changePage(pageNo) {
        this.pageData.pageNo = pageNo;
        this.update();
      },

      /* 监听分页条数的改变 */
      onShowSizeChange(current, pageSize) {
        this.pageData.pageSize = pageSize;
        this.pageData.pageNo = 1;
        this.update();
      },

      /* 获取绩效审核记录 */
      getAuditData(b) {
        if (b) { this.pageData.pageNo = 1; }
        let pageData = this.pageData;
        let param = {
          indexGroup: this.tableKey,          // 组织类型
          indexYearMonth: this.date,          // 时间 YYYYMM
          pageNo: pageData.pageNo,            // 跳转页数 默认 1
          pageSize: pageData.pageSize         // 分页数 默认 10
        }

        this.loading = true;
        apiConfig[this.k].getData(param).then((res) => {
          this.loading = false;
          let result = res.result || {};
          this.auditTabData.dataSource = result.records;
          this.pageData.total = result.total;
        }).catch((error) => {
          this.loading = false;
          this.pageData.total = null;
          this.$message.error(error.message);
        });
      },

      /* 更新表格数据 */
      update(b) {
        if (b) { this.pageData.pageNo = 1; }

        let pageData = this.pageData;
        let targets = (this.targets.length === 0) ? null : this.targets;
        let dimensions = (this.dimensions.length === 0) ? null : this.dimensions;
        let param = {
          indexGroup: this.tableKey,          // 组织类型
          indexYearMonth: this.date,          // 时间 YYYYMM
          indexCodes: targets,                // 考核指标
          indexAttrs: dimensions,             // 维度
          pageNo: pageData.pageNo,            // 跳转页数 默认 1
          pageSize: pageData.pageSize         // 分页数 默认 10
        }

        this.loading = true;
        this.$parent.isNotData = true;
        apiConfig[this.k].getData(param).then((res) => {
          this.loading = false;

          let result = res.result || {};
          let records = result.records;

          // 通知父级组件当前有数据
          if (records && records.length > 0) { this.$parent.isNotData = false; }

          this.tableData[this.tableKey].dataSource = records;
          this.editAllData = JSON.parse(JSON.stringify(records));
          this.pageData.total = result.total;
          this.editRowData = {};

          /* 为权重动态改变表头百分比 */
          if (this.k === 'weight') { this.changeColumns(result.weightTotal || {}); }

          /* 通知父组件 start */
          this.$parent.isSavingAll = false;
          this.$parent.switchEditTab();   // 1. 通知父组件更新【是否是批量编辑】状态
          this.updateIsEditRow();         // 2. 通知父组件更新【是否是单行编辑】状态

          // 当前是绩效汇总计算模块
          if (this.k === 'mgr') {
            this.$parent.getStatus();     // 3. 通知父组件更新【审核状态】
            this.$parent.getTaskStatus(); // 4. 通知父组件获取任务状态
          }
          /* 通知父组件 end */
        }).catch((error) => {
          this.loading = false;
          this.$parent.isSavingAll = false;
          this.pageData.total = null;
          this.$message.error(error.message);
        });
      },

      // 权重动态拼接百分比
      changeColumns(totals) {
        let columns = this.tableData[this.tableKey].columns;
        columns.forEach((item) => {
          let key = item.dataIndex;
          let str = item.title.split('(')[0];
          item.title = totals[key] ? str + '(' + totals[key] + ')' : str;
          item.className = (totals[key] && parseFloat(totals[key]) != 100) ? 'color-warning' : '';
        });
      },

      /* 保存编辑 | 得分计算 */
      submitData(fn) {
        let param = {
          indexGroup: this.tableKey,    // 组织类型
          indexYearMonth: this.date,    // 考核期 YYYYMM
          values: this.getEditData(),   // 需要保存的数组
        }

        this.loading = true;
        apiConfig[this.k][fn](param).then((res) => {
          if (!res.success) {
            this.loading = false;
            this.$parent.isSavingAll = false;
            this.$message.warning(res.message);
            return;
          }

          this.$message.success('操作成功');
          this.update();
        }).catch((error) => {
          this.loading = false;
          this.$parent.isSavingAll = false;
          this.$message.error(error.message);
        });
      },

      /* 取消编辑 */
      cancel() { this.$parent.switchEditTab(); },



      /* 点击某行进行编辑 */
      getNewTableData(tableData, tableKey, ind, str) {
        let t = this;
        let newTableData = {};

        for (let key in tableData) {
          let item = tableData[key];
          let dataSource = item.dataSource;

          /* 只需要处理当前选中的组织类型 */
          if (key === tableKey && dataSource[ind]) {

            /* cancel 点击取消按钮 */
            if (str === 'cancelRow') {
              t.editRowData = {};
              delete dataSource[ind]['isEditRow'];
            }

            /* edit 点击编辑行按钮  */
            if (str === 'editRow') {
              let rowDataSource = JSON.parse(JSON.stringify(dataSource[ind]));

              if (this.k === 'weight') {
                let arr = [{ ...rowDataSource }];
                t.editRowData = t.getWeightArr(arr, 'edit')[0];
              } else {
                t.editRowData = this.getDataSource(rowDataSource, 'edit');
              }

              dataSource[ind]['isEditRow'] = true;
            }
          }

          newTableData[key] = {
            scroll: item.scroll,
            columns: item.columns,
            dataSource: dataSource
          };
        }

        return newTableData;
      },

      /* 格式化 indexFormate = 3 为百分比的数据 */
      getDataSource(rowData, str) {
        let newRowData = rowData;

        if (rowData.indexFormate && rowData.indexFormate == '3') {
          let editArr = this.editDataKeys[this.tableKey];
          for (let i = 0; i < editArr.length; i++) {
            let key = editArr[i];

            if (rowData[key]) {
              if (str === 'edit') { newRowData[key] = parseFloat(rowData[key]); }
              if (str === 'save') { newRowData[key] = rowData[key] + '%'; }
            }
          }
        }

        return newRowData;
      },

      /**
       * 返回保存时需要的数组
       * 目前只有【权重管理 weight】模块需要将格式转化一下再保存
       * */
      getEditData() {
        // 如果是空对象，返回空数组
        if (Object.keys(this.editRowData).length === 0 && !this.isEditAll) { return []; }

        // 单行数据
        let rowArr = [{ ...this.editRowData }];

        /* 如果是权重模块 */
        if (this.k === 'weight') {
          /* 单行编辑情况 */
          if (!this.isEditAll) { return this.getWeightArr(rowArr, 'save'); }

          /* 批量编辑情况 */
          return this.getWeightArr(this.editAllData, 'save');
        }

        /* 单行编辑保存 */
        if (!this.isEditAll) {
          rowArr[0] = this.getDataSource(rowArr[0], 'save');
          return rowArr;
        }

        /* 返回全部列表 */
        let dataSource = JSON.parse(JSON.stringify(this.editAllData));
        for (let i = 0; i < dataSource.length; i++) {
          let item = dataSource[i];
          dataSource[i] = this.getDataSource(item, 'save');
        }
        return dataSource;
      },

      /**
       * 格式转化
       *
       * key => 标记组织唯一的键值 code
       * val => 适配 4 种格式 "12%" | 12 | "[1, 5]" | [1, 5]
       * n => 标记 1 = 百分比 | 2 = 区间
       * ope => 系统要做的操作 edit = 编辑操作 | save = 保存操作
       * */
      formatConversion(key, val, n, ope) {
        let editKeys = this.editDataKeys[this.tableKey];

        // 如果不符合条件，返回原数值
        if (editKeys.indexOf(key) < 0 || !ope) { return val; }

        // 如果是百分比，对应的 2 种格式为 "12%" | 12
        if (n === '1') {
          if (ope === 'edit') { return this.getNum(val); }
          if (ope === 'save') { return val + '%'; }
        }

        // 如果是区间，对应的 2 种格式为 "[1, 5]" | [1, 5]
        if (n === '2') {
          if (ope === 'edit') {
            // TODO 特殊处理一下 arr 后台格式不稳定 很有可能是字符串 "1,5" 的格式 需要转成数组，后期稳定后删除
            if (typeof val === 'string' && val[0] !== '[') {
              return val.split(',').map((val) => { return this.getNum(val); });
            }

            try {
              return JSON.parse(val);
            } catch (e) {
              return [0, 0];
            }
          }

          if (ope === 'save') {
            val[0] = parseFloat(val[0]);
            val[1] = parseFloat(val[1]);
            return val;
          }
        }
      },

      /**
       * 格式化权重管理的参数
       *
       * dataSource 表格数据
       * ope 对应的操作
       * */
      getWeightArr(dataSource, ope) {
        let newArr = [];

        for (let i = 0; i < dataSource.length; i++) {
          let objData = dataSource[i];

          for (let key in objData) {
            let item = objData[key];
            let indexType = objData.indexType;

            objData[key] = this.formatConversion(key, item, indexType, ope);
          }

          newArr.push(objData);
        }

        return newArr;
      }

    },
  };
</script>



<style lang="less" scoped>

  .spanStyle{
    //margin-top: 9px;
    white-space: nowrap;  /*强制span不换行*/
    display: inline-block;  /*将span当做块级元素对待*/
    width: 80px;  /*限制宽度*/
    //height: 20px;
    overflow: hidden;  /*超出宽度部分隐藏*/
    text-overflow: ellipsis;  /*超出部分以点号代替*/
    //line-height: 0.9;  /*数字与之前的文字对齐*/

  }
  .table-box {
    /*/deep/.ant-table th {
      white-space: nowrap;
      min-width: 90px;
    }*/

    /deep/.ant-table td {
      height: 44px;
      padding: 5px 10px;

      input {
        height: 28px;
        padding: 4px 5px;
      }

      .weight-per, .weight-sec {
        input { width: 40% }
      }
    }

    .pagination-box {
      margin-top: 20px;
      float: right;
    }

    .btn-edit,
    .btn-save,
    .btn-cancel {
      color: @primary-color;
      cursor: pointer;

      &:hover {
        text-decoration: underline;
      }
    }
    .btn-cancel {
      margin-left: 10px;
    }
    .btn-disabled {
      color: #cccccc;
    }

    /deep/.ant-table-thead > tr > th.color-warning { color: #F1523A; }
  }

  .weight-box table tr td {
    input::-webkit-outer-spin-button,
    input::-webkit-inner-spin-button {
      -webkit-appearance: none;
    }
    input[type='number'] {
      -moz-appearance: textfield;
    }
  }
</style>


